import datetime
import json
import time
from django.shortcuts import render,redirect,HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django_redis import get_redis_connection
from django.conf import settings
from utils.alipay import AliPay
from utils.encrypt import uid
from web.models import IssuesType
from  web.form.project import ProjectAddModelForm
from utils.tencent.cos import creat_bucket,bucket_cors,get_credential_demo
from django.http import JsonResponse
from pinyin import pinyin
from web import models

def list(request):
    """项目列表"""
    # GET用于展示项目列表
    if request.method == "GET":
        '''
            将三类数据: ①星标
                      ②我创建的项目
                      ③我参与的项目
            处理出来后返回给前端循环出来展示
        '''
        project_dict = {"star":[],"my":[],"join":[]}
        my_project_list = models.Project.objects.filter(creator=request.transaction.user) # 我创建的所有项目的对象列表
        for row in my_project_list:
            if row.star:
                project_dict["star"].append({"data":row,"type":"my"})
            else:
                 project_dict["my"].append(row)
        join_project_list = models.ProjectUser.objects.filter(user=request.transaction.user) # 我参与的所有项目的对象列表
        for item in join_project_list:
            if item.star:
                project_dict["star"].append({"data":item.project,"type":"join"})
            else:
                project_dict["join"].append(item.project)

        form = ProjectAddModelForm(request)
        return render(request,'project_list.html',{"form":form,"project_dict":project_dict})

    # post添加项目
    form = ProjectAddModelForm(request,data=request.POST)
    if form.is_valid():
        # 创建项目时创建一个桶,名称用手机号+时间+后缀
        name = form.cleaned_data["name"]                 # pinyin.get()里加上format='strip'就是返回不带音标的拼音，默认会带音标
        bucket = '{}-{}-{}-1315656446'.format(str(pinyin.get(name,format='strip')),request.transaction.user.mobile_phone,str(round(time.time())))
        creat_bucket(bucket=bucket,region='ap-chengdu') # 创建一个桶
        bucket_cors(bucket=bucket,region='ap-chengdu') # 为桶做跨域策略
        form.instance.bucket = bucket
        form.instance.region = 'ap-chengdu'
        form.instance.creator = request.transaction.user # 将当前用户传给form的创建人字段
        instance = form.save()
        # 项目创建后为项目创建几个问题类型
        pro_list = []
        for i  in IssuesType.PROJECT_INIT_LIST: # ["任务", '功能', 'Bug']
             pro_list.append(models.IssuesType(project=instance,title=i))
        models.IssuesType.objects.bulk_create(pro_list)

        return JsonResponse({"status":True})
    return JsonResponse({"status":False,"errors":form.errors})


def star(request,project_type,project_id):
    if project_type =='my':
        models.Project.objects.filter(id=project_id).update(star=True)
        return redirect("/project/list/")
    if project_type == 'join':
        models.ProjectUser.objects.filter(project_id=project_id).update(star=True)
        return redirect("/project/list/")
    return HttpResponse("请求错误")

def unstar(request,project_type,project_id):
    if project_type =='my':
        models.Project.objects.filter(id=project_id).update(star=False)
        return redirect("/project/list/")
    if project_type == 'join':
        models.ProjectUser.objects.filter(project_id=project_id).update(star=False)
        return redirect("/project/list/")
    return HttpResponse("请求错误")


def pay_index(request):
    data = models.PricePolicy.objects.filter(category=2)
    return render(request,"pay_index.html",{"data":data})



def payment(request, price_type):
    """ 支付页面"""
    # 1. 价格策略（套餐）policy_id
    policy_object = models.PricePolicy.objects.filter(id=price_type, category=2).first()
    if not policy_object:
        print("not policy_object")
        return redirect('pay_index')

    # 2. 要购买的数量
    number = request.POST.get('number', '')
    if not number or not number.isdecimal():
        print("not number or not number.isdecimal()")
        return redirect('pay_index')
    number = int(number)
    if number < 1:
        print("number < 1")
        return redirect('pay_index')

    # 3. 计算原价
    origin_price = number * policy_object.price

    # 4.之前购买过套餐(之前掏钱买过）
    balance = 0
    _object = None
    if request.transaction.price_policy.category == 2:
        # 找到之前订单：总支付费用 、 开始~结束时间、剩余天数 = 抵扣的钱
        # 之前的实际支付价格
        _object = models.Transaction.objects.filter(user=request.transaction.user, status=2).order_by('-id').first()
        total_timedelta = _object.end_datetime - _object.start_datetime
        balance_timedelta = _object.end_datetime - datetime.datetime.now()
        if total_timedelta.days == balance_timedelta.days:
            # 按照价值进行计算抵扣金额
            balance = _object.price_policy * policy_object.price * _object.count / total_timedelta.days * (balance_timedelta.days - 1)
        else:
            balance = _object.price_policy * policy_object.price * _object.count / total_timedelta.days * balance_timedelta.days

    if balance >= origin_price:
        print("balance >= origin_price")
        return redirect('pay_index')

    context = {
        'policy_id': policy_object.id,
        'number': number,
        'origin_price': origin_price,
        'balance': round(balance, 2),
        'total_price': origin_price - round(balance, 2)
    }
    conn = get_redis_connection()
    key = 'payment_{}'.format(request.transaction.user.mobile_phone)
    # conn.set(key, json.dumps(context), nx=60 * 30)
    conn.set(key, json.dumps(context), ex=60 * 30)  # nx参数写错了，应该是ex（表示超时时间） ps：nx=True,表示redis中已存在key，再次执行时候就不会再设置了。

    context['policy_object'] = policy_object
    context['transaction'] = _object
    print(context)
    return render(request, 'payment.html', context)
'''
def pay(request):

    conn = get_redis_connection()
    key = 'payment_{}'.format(request.transaction.user.mobile_phone)
    context_string = conn.get(key)
    if not context_string:
        return redirect('price')
    context = json.loads(context_string.decode('utf-8'))

    # 1. 数据库中生成交易记录（待支付）
    #     等支付成功之后，我们需要把订单的状态更新为已支付、开始&结束时间
    order_id = uid(request.transaction.user.mobile_phone)
    total_price = context['total_price']
    models.Transaction.objects.create(
        status=1,
        order=order_id,
        user=request.transaction.user,
        price_policy_id=context['policy_id'],
        count=context['number'],
        price=total_price
    )

    # 2. 跳转到支付去支付
    #    - 根据申请的支付的信息 + 支付宝的文档 => 跳转链接
    #    - 生成一个支付的链接
    #    - 跳转到这个链接
    # 构造字典
    params = {
        'app_id': "2021000122680481",   # appid
        'method': 'alipay.trade.page.pay', # 接口
        'format': 'JSON',
        'return_url': "http://127.0.0.1:8000/pay_notify/", # get回调地址
        'notify_url': "http://127.0.0.1:8000/pay_notify/", # post回调地址
        'charset': 'utf-8',
        'sign_type': 'RSA2',
        'timestamp': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        'version': '1.0',
        'biz_content': json.dumps({
            'out_trade_no': order_id,
            'product_code': 'FAST_INSTANT_TRADE_PAY',
            'total_amount': total_price,
            'subject': "tracer payment"
        }, separators=(',', ':'))
    }

    # 获取待签名的字符串
    unsigned_string = "&".join(["{0}={1}".format(k, params[k]) for k in sorted(params)])

    # 签名 SHA256WithRSA(对应sign_type为RSA2)
    from Crypto.PublicKey import RSA
    from Crypto.Signature import PKCS1_v1_5
    from Crypto.Hash import SHA256
    from base64 import decodebytes, encodebytes

    # SHA256WithRSA + 应用私钥 对待签名的字符串 进行签名
    private_key = RSA.importKey(open("file/应用私钥.txt").read())
    signer = PKCS1_v1_5.new(private_key)
    signature = signer.sign(SHA256.new(unsigned_string.encode('utf-8')))

    # 对签名之后的执行进行base64 编码，转换为字符串
    sign_string = encodebytes(signature).decode("utf8").replace('\n', '')

    # 把生成的签名赋值给sign参数，拼接到请求参数中。

    from urllib.parse import quote_plus
    result = "&".join(["{0}={1}".format(k, quote_plus(params[k])) for k in sorted(params)])
    result = result + "&sign=" + quote_plus(sign_string)

    gateway = "https://openapi.alipaydev.com/gateway.do"
    ali_pay_url = "{}?{}".format(gateway, result)
    print(ali_pay_url)
    return redirect(ali_pay_url)
'''
def pay(request):
    conn = get_redis_connection()
    key = 'payment_{}'.format(request.transaction.user.mobile_phone)
    context_string = conn.get(key)
    if not context_string:
        return redirect('price')
    context = json.loads(context_string.decode('utf-8'))

    # 1. 数据库中生成交易记录（待支付）
    #     等支付成功之后，我们需要把订单的状态更新为已支付、开始&结束时间
    order_id = uid(request.transaction.user.mobile_phone)
    total_price = context['total_price']
    models.Transaction.objects.create(
        status=1,
        order=order_id,
        user=request.transaction.user,
        price_policy_id=context['policy_id'],
        count=context['number'],
        price=total_price
    )
    # 生成支付链接

    ali_pay = AliPay(
        appid=settings.ALI_APPID,
        app_notify_url=settings.ALI_NOTIFY_URL,
        return_url=settings.ALI_RETURN_URL,
        app_private_key_path=settings.ALI_PRI_KEY_PATH,
        alipay_public_key_path=settings.ALI_PUB_KEY_PATH
    )
    query_params = ali_pay.direct_pay(
        subject="trace rpayment",  # 商品简单描述
        out_trade_no=order_id,  # 商户订单号
        total_amount=total_price
    )
    pay_url = "{}?{}".format(settings.ALI_GATEWAY, query_params)
    print(pay_url)
    return redirect(pay_url)


def notify(request):
    """ 支付成功之后触发的URL """
    ali_pay = AliPay(
        appid=settings.ALI_APPID,
        app_notify_url=settings.ALI_NOTIFY_URL,
        return_url=settings.ALI_RETURN_URL,
        app_private_key_path=settings.ALI_PRI_KEY_PATH,
        alipay_public_key_path=settings.ALI_PUB_KEY_PATH
    )

    if request.method == 'GET':
        # 只做跳转，判断是否支付成功了，不做订单的状态更新。
        # 支付吧会讲订单号返回：获取订单ID，然后根据订单ID做状态更新 + 认证。
        # 支付宝公钥对支付给我返回的数据request.GET 进行检查，通过则表示这是支付宝返还的接口。
        params = request.GET.dict()
        sign = params.pop('sign', None)
        status = ali_pay.verify(params, sign) # 用支付宝公钥去验证是否支付成功
        if status:
            """
            current_datetime = datetime.datetime.now()
            out_trade_no = params['out_trade_no']
            _object = models.Transaction.objects.filter(order=out_trade_no).first()

            _object.status = 2
            _object.start_datetime = current_datetime             改生效时间
            _object.end_datetime = current_datetime + datetime.timedelta(days=365 * _object.count)
            _object.save()
            """
            return HttpResponse('支付完成')
        return HttpResponse('支付失败')
    else:
        from urllib.parse import parse_qs
        body_str = request.body.decode('utf-8')
        post_data = parse_qs(body_str)
        post_dict = {}
        for k, v in post_data.items():
            post_dict[k] = v[0]

        sign = post_dict.pop('sign', None)
        status = ali_pay.verify(post_dict, sign)
        if status:
            current_datetime = datetime.datetime.now()
            out_trade_no = post_dict['out_trade_no']
            _object = models.Transaction.objects.filter(order=out_trade_no).first()

            _object.status = 2
            _object.start_datetime = current_datetime
            _object.end_datetime = current_datetime + datetime.timedelta(days=365 * _object.count)
            _object.save()
            return HttpResponse('success')

        return HttpResponse('error')